function map_to_list(m) {
  var id_map = {}; // map from string id to position in the list.
  var result = { list:[], id_map:{} }; // the graph for display by Amoeba.

  var i = 0;
  for (var k in m) {
    result.id_map[k] = i;
    result.list.push(m[k]);
    i++;
  }
  return result;
};

var invert_map = function (m) {
  var new_m = {};
  for (var k in m) {
    if(m.hasOwnProperty(k)) {
      new_m[m[k]] = k;
    }
  }
  return new_m;
};

function close_profile() {
    document.getElementById('pillar-profile-content').innerHTML = "";
    $('#pillar-profile').addClass('hidden');
}
function show_profile() {
    $('#pillar-profile').removeClass('hidden');
}

function prepare_graph(g) {
  var amoeba_graph = { nodes:[], edges:[] }; // the graph for display by Amoeba.

  var r = map_to_list(g.nodes);
  var id_map = r.id_map;
  amoeba_graph['nodes'] = r.list;

  // Hack using JS table of real-names in order to do translation.
  // TODO: generate correct names in python.
  for(var i = 0; i < amoeba_graph['nodes'].length; i++) {
    // People are messy when entering data - push everything to lower-case,
    // and drop random spaces.
    amoeba_graph['nodes'][i]['className'] = amoeba_graph['nodes'][i]['className'].trim().toLowerCase();
    //
    if(amoeba_graph['nodes'][i]['className'] == "category") {
      amoeba_graph['nodes'][i]['name'] =
          // TODO: fix bad hacky escaping which emulates django escapes in
          // index.html template.
          category_descriptions["category_" + amoeba_graph['nodes'][i]['name'].trim().replace(/&/g, "&amp;")];
    }
  }

  /* TODO: add in fixing of central node to position 0,
  var arity = {}; // arity of each vertex.

  // select vertices which are not category vertices and which
  for(var i = 0; i < amoeba_graph.length; i++) {
    if(amoeba_graph[i]['className'] != "category") {
      if()
    }
  }
   */

  // assumes ids only appear in from and to.
  for(var i = 0; i < g.edges.length; i++) {
    var new_e = g.edges[i];
    new_e['from'] = id_map[g.edges[i]['from']];
    new_e['to'] = id_map[g.edges[i]['to']];
    amoeba_graph.edges.push(new_e);
  }

  var result = {
    id_map: id_map,
    graph: amoeba_graph
  };

  return result;
};

function init() {

  var viewconfig = {
    showLabels: true,
    autoZoom: true,
    //showBlockedLabels: true,
    // disableWebGl: true,

    // This is the style description. It looks similar to CSS, but is actually Javascript. See:
    // https://sites.google.com/a/google.com/amoeba/documentation/javascript-api-styling
    styles: {
      // Adjustments to the base graph style.
      graph: {
        tension: 5,
        density: 15,
        backgroundColor: '#f1f1f1',
      },

      // Adjustments for the node style.
      node: {
        scale: 1,
        color: '#afafaf',
        fontScale: 1.3,
        fontFamily: 'sans-serif',
        //fontStyle: 'italic',
        labelPosition: 'below',
      },

      // Adjustments for the edge style.
      edge: {
        scale: 1.5,
        color: '#ccc',
      },

      // end-node visualisation
      defected: {
        color: '#d42222',
        //icon: '/static/img/defected.png',
      },

      defectedrecently: {
        color: '#ff9900',
        //icon: '/static/img/latestdefect.png',
      },

      active: {
        color: '#999',
        labelPosition: 'below',
        //icon: '/static/img/dead.png',
      },

      inactive: {
        color: '#999',
        labelPosition: 'below',
        //icon: '/static/img/dead.png',
      },

      deceased: {
        color: '#FFF',
        labelPosition: 'below',
        //icon: '/static/img/dead.png',
      },

      categoryEdge : {
        //tension: 10,
        // minRadius: 4,
        //  maxRadius: 10,
      },

      //
      category: {
        fontFamily: 'sans-serif',
        fontStyle: 'bold',
        fontScale: 4,
        scale: 0.5,
        labelPosition: 'center',
        color: '#ccc',
      },
    }
  };
  var view = new amoeba.GraphView(document.getElementById('graph'), viewconfig);
  var pos_to_id_map = {};
  //var supportnetwork = {};
  $.ajax(
      { "url" : LANGUAGE_URL + "/graph/json/",
        "type" : "GET",
        "success" :  function(data, textStatus, jqXHR) {
          var r = prepare_graph(data);
          pos_to_id_map = invert_map(r.id_map);

          $('#graph-loading-message').addClass('hidden');
          view.setGraph(amoeba.Graph.fromDescription(r.graph));
        },
        "error" : function(jqXHR, textStatus, errorThrown){
          console.log("AJAX query for jason graph object failed.");
        }
      });

  // Register event listeners for clicks and mouse events on nodes:
  view.addEventListener('node-click', function(e) {

    var long_id = '' + pos_to_id_map[e.node.id];
    var node_type = long_id.substr(0,1);
    var node_id = long_id.substr(2,long_id.length - 2);

    console.log({nid:e.node.id, long_id:long_id});
    if (node_type == "n") {
      document.getElementById('pillar-profile-content').innerHTML = loading_message;
      show_profile();
      $.ajax(
          { "url" : "node/html/",
            "data" : { "id": node_id },
            "type" : "GET",
            "success" :  function(data, textStatus, jqXHR) {
              var s = "";
              document.getElementById('pillar-profile-content').innerHTML = data;
            },
            "error" : function(jqXHR, textStatus, errorThrown){
              console.log("AJAX query for jason graph object failed.");
            }
          });
    }
  });

  // Clicked on the background
  view.addEventListener('click', function(e) {
    close_profile();
  });

  // Other things that you can do...
  /* view.addEventListener('node-mouseover', function(e) {
    document.getElementById('debug_mouse').innerHTML =
        'Mouseover: ' + e.node.name + ' (' + e.node.id + ')';
  });
  view.addEventListener('node-mouseout', function(e) {
    document.getElementById('debug_mouse').innerHTML =
        'Mouseout: ' + e.node.name + ' (' + e.node.id + ')';
  });
  view.addEventListener('node-mousemove', function(e) {
    document.getElementById('debug_mouse').innerHTML =
        'Mousemove: ' + e.node.name + ' (' + e.node.id + ') @ ' +
        e.offsetX + ',' + e.offsetY;
  });*/
}